1. ¿Qué son git y GitHub?

git es un programa que sirve para rastrear los cambios en las versiones de un programa o proyecto ("version control system", o VCS). Se puede usar desde la línea de comandos; permite checar cambios en cualquier punto de la historia, resetear a algún punto específico del historial, tener desarrollos independientes, etc. Es código abierto. Fue inventado por Linus Torvalds en el 2005 para el manejo y desarrollo del kernel de Linux. En pocas palabras, es un manejador de repositorios.

GitHub es un sitio-web/red social donde uno puede hacer un desarrollo colaborativo de algún proyecto, de forma abierta o cerrada, y permite hacer respaldos en la nube. Actualmente, es donde se realizan la mayor parte de los proyectos abiertos.

Los comandos debajo están diseñados para usarse en sistemas tipo Unix, es decir en Linux y Mac. Para usarlos en Windows, es necesario instalar Git Bash y llevar a cabo los comandos directamente desde Git Bash (no desde el Notebook). También en Linux y Mac los comandos se pueden teclear directamente desde la terminal. Para hacerlo, simplemente no se escriben los ; al principio de los comandos.

2. Creación de un repositorio git y primeros pasos

git es un manejador de repositorios con mucha flexibilidad. Un repositorio es un directorio donde se almacena el desarrollo de un proyecto.

git, en lugar de hacer copias de cada archivo y cada uno de los cambios del proyecto, lo que hace es guardar los cambios en ciertos puntos de la historia, que el usuario define.

Antes de iniciar, el repositorio, veamos la estructura actual del directorio (que vale la pena, por ahora, que sea "git-test"). Para esto, desde la terminal, ejecutamos:

ls -alp

Esto, se puede hacer desde julia o IJulia usando ;, que manda un comando a la terminal / línea de comandos:

; ls -alp

In [2]:
; ls -alp


total 8
drwxr-xr-x   4 benet  staff   136 Feb  2 17:28 ./
drwxr-xr-x  15 benet  staff   510 Jan 21 10:51 ../
drwxr-xr-x   3 benet  staff   102 Feb  2 16:52 .ipynb_checkpoints/
-rw-------   1 benet  staff  2726 Feb  2 17:28 01-git.ipynb

El directorio ".ipynb_checkpoints/" incluye información de los distintos puntos donde he salvado este "ipython notebook", que de hecho es un "ijulia notebook". El otro archivo, es la versión actual de este notebook.

Para empezar un repositorio git, hay que ejecutar la instrucción

; git init

Ejercicio 1: Crea un directorio nuevo que se llama git-test [recuerda que el comando de Linux para crear un directorio es mkdir, y para cambiar al directorio es cd] e inicializa tu repositorio git ahí; hazlo sin miedo. NOTA: La celda vacía que hay abajo es para que hagas el ejercicio. Asegúrate de que el archivo 01-git.ipynb se encuentre en este directorio (moverlo ahí si es necesario y vuelve a abrir el Notebook desde ahí).


In [ ]:

Una vez que lo hayan hecho, el contenido de su directorio debería verse como sigue:


In [4]:
;ls -alp


total 8
drwxr-xr-x   5 benet  staff   170 Feb  2 17:31 ./
drwxr-xr-x  15 benet  staff   510 Jan 21 10:51 ../
drwxr-xr-x   9 benet  staff   306 Feb  2 17:31 .git/
drwxr-xr-x   3 benet  staff   102 Feb  2 16:52 .ipynb_checkpoints/
-rw-------   1 benet  staff  3749 Feb  2 17:30 01-git.ipynb

Entonces, el comando git init crea el directorio escondido .git/ que contendrá toda la información del repositorio, en este caso, el contenido de este curso. (Nota que hay un punto, ".", antes de "git". Eso corresponde a un archivo o directorio escondido.)

Ejercicio 2: (Desde el IJulia notebook) ¿Qué hay dentro del directorio .git? (Hint: recuerden lo que hace ; antes de una instrucción de linux.)


In [ ]:

Antes de seguir adelante, conviene que ejecuten los siguientes comandos, con los cambios apropiados a ustedes:

git config --global user.name "Luis Benet"
git config --global user.email "benet@fis.unam.mx"
git config --global color.ui "auto"

Estos comandos tienen como objetivo configurar la cuenta desde donde están trabajando. Los dos primeros sirven para que los cambios que hagan queden debidamente firmados, por así decirlo; el último sirve para ver la vida de colores, desde la terminal :-)

Para ver la situación o status del repo, ejecutamos la instrucción

git status

In [5]:
; git status


On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.ipynb_checkpoints/
	01-git.ipynb

nothing added to commit but untracked files present (use "git add" to track)

A fin de interpretar el contenido de la salida de

git status

empezaremos por definir ciertos términos:

  • Cada punto de la historia de un repositorio se guarda en "branches" (ramas).
  • En el tiempo, el usuario puede decidir guardar una representación de ese momento del desarrollo del proyecto. Cada uno de esas fotografías del desarrollo se llaman "commits", y el guardar la historia es hacer un commit, del inglés, committing.

Entonces, el resultado de git status indica:

  • Que estamos en la rama master; de ahora en adelante, en el branch master, que es el de default y, de hecho, el principal.
  • Que estamos en el commit inicial, es decir, que no se ha guardado ningún cambio aún en el repositorio.
  • Que hay dos archivos cuyos cambios, en este momento, no se están siguiendo: untracked files.
  • Y, lo más importante, qué es lo que hay que hacer para hacer que la historia de uno o varios archivos sea seguida. O sea, que esos archivos sean tracked: (use "git add" to track)

Vayamos paso a paso. Nos interesa seguir los cambios de "01-git.ipynb"; después veremos cómo se puede ignorar los cambios en ".ipynb-checkpoints/". Entonces, siguiendo lo que nos dice, ejecutaremos:

git add 01-git,ipynb

Pero, antes, vale la pena salvar la situación actual de este archivo.

NOTA Yo haré esto desde IJulia, pero puede ser más conveniente hacerlo desde la propia terminal; así, uno evita hacer cosas que cambian este archivo. Si lo hacen desde la terminal, recuerden no poner el ;.


In [6]:
; git add 01-git.ipynb

Mmmmmm...

¿Pasó algo? Veamos qué dice git status; nuevamente, es mejor hacerlo desde la terminal.


In [10]:
; git status


On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   01-git.ipynb

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.ipynb_checkpoints/

A pesar de que aún no hemos guardado este punto en la historia del proyecto (Changes to be committed:), vemos que git ahora nos avisa de los cambios que serán hechos: se incluirá el nuevo archivo 01-git.ipynb. Y también, cómo dar marcha atrás a los cambios: (use "git rm --cached <file>..." to unstage); pero esto lo dejaremos para más tarde.

Para guardar este punto de la historia del proyecto ejecutaremos:

git commit -m "Add 01-git.ipynb"

Aquí, la bandera -m avisa que escribiremos una línea de mensaje, escrito entre comillas. Ese mensaje habla de los cambios que se hicieron (de manera resumida) y sirven como recordatorio.

NOTA: De igual manera uno puede escribir la línea de resumen y más detalles de los cambios que se guardan, cosa que obviamente es beneficiosa. Para esto último, uno ejecutaría git commit (sin ninguna bandera ni nada más); esto abrirá un editor, por default "vi", donde escribiremos una línea de resumen, y dejando un espacio en blanco, lo que queramos más detallado. Esto conviene hacerlo desde la terminal.

Ver aquí para una guía de "buenas prácticas" sobre cómo escribir los mensajes en los commits; vale la pena leerlo!


In [11]:
; git commit -m "Add 01-git.ipynb"


[master (root-commit) 3225b9d] Add 01-git.ipynb
 1 file changed, 315 insertions(+)
 create mode 100644 01-git.ipynb

El mensaje indica que hemos hecho el primer commit, etiquetado "3225b9d", y que éste incluye 315 inserciones. Esta etiqueta (que podría ser otra para ustedes), que de hecho es una etiqueta abreviada, se llama "hash".

Ejercicio 3: ¿Qué indica git status ahora?


In [ ]:

Para saber más detalles de la historia del repositorio, o sea, echarle un ojo a la bitácora (log), uno utiliza la instrucción

git log

In [13]:
; git log


commit 3225b9d8cbd4722805a73ede1c2fe4a247de82a9
Author: Luis Benet <benet@fis.unam.mx>
Date:   Mon Feb 2 18:27:27 2015 -0600

    Add 01-git.ipynb

Aquí ven por qué arriba dije que la etiqueta es abreviada; también ven que yo hice los cambios, cuando, y mi email.

Desde que hice el commit inicial, de hecho, muuuuucho he escrito. Para darme cuenta de ello, un simple git status basta y sobra. Ahí veré que el archivo 01-git.ipynb ha sido modificado, y que .ipynb_checkpoints/ aparece como untracked. Ahora, veremos cómo hacer para que ciertos archivos simplemente no se consideren en la lista; en particular, que .ipynb_checkpoints/ no aparezca nuevamente.

Empecemos por crear el archivo .gitignore vacío; noten que es un archivo escondido:

touch .gitignore

Ahora, yo escribiré desde la línea de comandos .ipynb_checkpoints en ese archivo. Esto se logra con:

echo ".ipynb_checkpoints" > .gitignore

Ejercicio 4: Creen un archivo que se llame .gitignore con el contenido arriba mencionado.


In [ ]:

Si todo va bien hasta aquí, entonces podemos ver el contenido del archivo .gitignore con el comando cat:


In [15]:
; cat .gitignore


.ipynb_checkpoints

In [16]:
; git status


On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   01-git.ipynb

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.gitignore

no changes added to commit (use "git add" and/or "git commit -a")

Por un lado, he modificado el archivo "01-git.ipynb"; además, hay un nuevo archivo que no está siendo seguido por git: .gitignore. El punto que resaltar es que el dichoso directorio .ipynb_checkpoints ya no aparece en la lista de los archivos que no se están siguiendo. Esto es justamente lo que hace el archivo .gitignore.

Ejercicio 5: Agreguen ese archivo a la lista de los archivos que serán seguidos en el respositorio. ¿Qué resulta dar git status después de agregar ese archivo? Después, hagan el commit relacionado a ese cambio. Para el mensaje del commit, ¡ejerciten su inglés!


In [ ]:

Ejercicio 6: ¿Qué hay nuevo en la salida de git log?


In [ ]:

Ahora haré un cambio trivial y no importante en ".gitignore":


In [17]:
; echo ".DS_Store" >> .gitignore

In [18]:
; git status


On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   .gitignore
	modified:   01-git.ipynb

no changes added to commit (use "git add" and/or "git commit -a")

Claramente, git nota que ha habido cambios en ambos archivos: en "01-git.ipynb" son los cambios asociados con lo que voy escribiendo ---y que por lo mismo, evitaremos ir comentando---, y el cambio en ".gitignore" que acabo de hacer. Para saber qué cambios he hecho en ".gitignore" usamos el comando git diff .gitignore:


In [19]:
; git diff .gitignore


diff --git a/.gitignore b/.gitignore
index 763513e..b5f2b45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 .ipynb_checkpoints
+.DS_Store

La información muestra que se agregó una línea: +.DS_Store y su contenido. Cambios más complejos se señalarán de igual manera, pero no les recomiendo hacer esto con "01-git.ipynb". Incidentalmente, en la terminal las diferencias se ven con colores.

Ahora, si por alguna razón queremos revertir los cambios, que por cierto justo ahora no hemos guardado, entonces, siguiendo las instrucciones que están en git status, ejecutamos:

git checkout -- .gitignore

In [20]:
; git checkout -- .gitignore

In [21]:
; cat .gitignore


.ipynb_checkpoints

Como se puede apreciar, hemos borrado los cambios en ese archivo y hemos vuelto al estado del último commit.

Esto nos lleva a un comentario importante: si bien uno puede borrar un archivo con rm archivo desde la terminal, esto no implica que git deje de ser checando los cambios a ese archivo. Si uno quiere borrar un archivo y que también desaparezca de ser seguido por git, uno debe además ejecutar:

git rm archivo

Resumiendo, el ciclo típico de desarrollo, desde el punto de vista de git es:

> git status   # ver cuál es la situación
[Modificar archivos]
> git status   # revisar cambios
> git add *archivo*  # prepara los archivos que se cambiaron
> git commit -m "Mensaje"

3. Subiendo los cambios del repositorio

Una característica de git es que permite subir los cambios en el repositorio a algún servidor central o un directorio de uso compratido. En particular, permite subir los cambios a GitHub, donde se puede tener un respaldo del repositorio de manera gratuita, siempre y cuando sea de código abierto.

Lo primero necesario, obviamente, es abrir una cuenta en GitHub, y entonces crear un nuevo repositorio; las instrucciones se encuentran aquí. Una vez que se ha creado el repositorio, GitHub explica los comandos que hay que usar para subir los cambios (push) a GitHub. Éstos son:

> git remote add origin https://github.com/NombreUsuario/Proyecto.git
> git push -u origin master

Aquí, "NombreUsuario" es el nombre de identificación ante GitHub (el suyo o el del desarrollador principal del repositorio), y "Proyecto" es el nombre del repositorio. Entonces, la primer instrucción define (configura) el lugar remoto donde se subirán los cambios, en este caso a GitHub; la segunda instrucción sube los cambios del branch master del repositorio local al repositorio remoto.

Por ahora dejaremos esto, pero eventualmente será algo importante, sobretodo en la parte colaborativa.

Referencias